package BLC

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"math"
	"math/big"
)

var (
	maxNonce=math.MaxInt64
)

const targetBits=12

type ProofOfWork struct{
	block *Block
	target *big.Int
}

func NewProofOfWork(block *Block)*ProofOfWork{
	target:=big.NewInt(1)
	target.Lsh(target,uint(256-targetBits))
	return &ProofOfWork{block,target}
}


func (p *ProofOfWork)prepareData(nonce int)[]byte{
	headers:=bytes.Join([][]byte{
		IntToHex(p.block.TimeStamp),
		p.block.PreviewHash,
		p.block.HashTransactions(),
		p.block.Hash,
		IntToHex(int64(targetBits)),
		IntToHex(int64(nonce)),
		IntToHex(p.block.Height),
	},[]byte{})
	return headers
}



func (p *ProofOfWork)Run()(int,[]byte){
	//把东西转化成byte类型，只是在原来的占的内存的大小转化成byte数组来控制而已，而byte只是uint类型
	var hashInt big.Int
	var hash [32]byte
	nonce:=0
	fmt.Printf("正在挖矿...")
	for nonce<maxNonce{
		headers:=p.prepareData(nonce)
		hash=sha256.Sum256(headers)
		fmt.Printf("nonce:%d,hash:%x\n",nonce,hash)
		hashInt.SetBytes(hash[:])//把字节数组转化成大的整数
		if hashInt.Cmp(p.target)==-1{//让两个整数进行比较，如果小于target就是-1
			break
		}else{
			nonce++
		}
	}
	return nonce,hash[:]
}

//对区块生成的东西进行验证
func (p *ProofOfWork)Validate(block *Block)bool{
	headers:=bytes.Join([][]byte{
		IntToHex(block.TimeStamp),
		block.PreviewHash,
		block.HashTransactions(),
		block.Hash,
		IntToHex(int64(targetBits)),
		IntToHex(int64(block.Nonce)),
		IntToHex(int64(block.Height)),
	},[]byte{})
	var hashInt big.Int
	hashInt.SetBytes(headers)
	if hashInt.Cmp(p.target)==-1{
		return true
	}
	return false
}